#include "TokenStream.h"


TokenStream::TokenStream(void)
{
  this->ResetStream();
}

TokenStream::~TokenStream()
{
}

void TokenStream::ResetStream(void)
{
  this->m_startIndex = this->m_endIndex = 0;
}

void TokenStream::SetTokenStream(char* data)
{
  this->ResetStream();
  this->m_data = data;
}

bool TokenStream::IsValidIdentifier(char c)
{
  if((int) c > 32 && (int) c < 127)
    return true;

  return false;
}

bool TokenStream::IsValidIdentifier(char c, char* delimiters, int totalDelimiters)
{
  if(delimiters == 0 || totalDelimiters == 0)
    return this->IsValidIdentifier(c);

  for(int i = 0; i < totalDelimiters; ++i)
  {
    if(c == delimiters[i])
      return false;
  }

  return true;
}


bool TokenStream::GetNextToken(std::string* buffer, char* delimiters, int totalDelimiters)
{
  this->m_startIndex = this->m_endIndex;

  bool inString = false;
  int len = (int) this->m_data.length();

  if(this->m_startIndex >= len - 1)
    return false;

  while(this->m_startIndex < len && this->IsValidIdentifier(this->m_data[this->m_startIndex], delimiters, totalDelimiters) == false)
  {
    ++this->m_startIndex;
  }

  this->m_endIndex = this->m_startIndex + 1;

  if(this->m_data[this->m_startIndex] == '"')
    inString = !inString;

  if(this->m_startIndex < len)
  {
    while(this->m_endIndex < len && (this->IsValidIdentifier(this->m_data[this->m_endIndex], delimiters, totalDelimiters) || inString == true))
    {
      if(this->m_data[this->m_endIndex] == '"')
        inString = !inString;
      ++this->m_endIndex;
    }

    if(buffer != nullptr)
    {
      int size = (this->m_endIndex - this->m_startIndex);
      int index = this->m_startIndex;

      buffer->reserve(size + 1);
      buffer->clear();

      for(int i = 0; i < size; ++i)
      {
        buffer->push_back(this->m_data[index++]);
      }
    }
    
    return true;
  }

  return false;
}

bool TokenStream::MoveToNextLine(std::string* buffer)
{
  int len = (int) this->m_data.length();

  if(this->m_startIndex < len && this->m_endIndex < len) 
  {
    this->m_endIndex = this->m_startIndex;

    while(this->m_endIndex < len && (this->IsValidIdentifier(this->m_data[this->m_endIndex]) || this->m_data[this->m_endIndex] == ' '))
      ++this->m_endIndex;

    if((this->m_endIndex - this->m_startIndex) == 0)
      return false;

    if((this->m_endIndex - this->m_startIndex) >= len)
      return false;

    if(buffer != nullptr)
    {
      int size = (this->m_endIndex - this->m_startIndex);
      int index = this->m_startIndex;

      buffer->reserve(size + 1);
      buffer->clear();

      for(int i = 0; i < size; ++i)
        buffer->push_back(this->m_data[index++]);
    }
  }
  else
  {
    return false;
  }

  ++this->m_endIndex;
  this->m_startIndex = this->m_endIndex + 1;
  
  return true;
}